package treepro;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;

/**
 *
 * @author Ivan
 */
public class LineObject extends GraphicObject {

    private Line2D line = new Line2D.Double();
    public static int clickAccuracy = 5;
    private NodeObject no1 = null;
    private NodeObject no2 = null;
    
    
    public double speed = 1.0;
    public float distance = 1.0f;
    public boolean orient = false;
    public boolean osob = false;
    public boolean nesimetr = false;
    

    public LineObject(float distance, boolean nesimetr, boolean orient, boolean osob, double speed, int no1, int no2, String name) {
        this(TreeProApp.main.treePanel, name, TreeProApp.main.treePanel.findByNumber(no1), TreeProApp.main.treePanel.findByNumber(no2));
        this.distance = distance;
        this.speed = speed;
        this.nesimetr = nesimetr;
        this.osob = osob;
        this.orient = orient;
    }
    
    

    public boolean isMyNode(int no1, int no2) {
        return ((this.no1.getNumber()==no1)&&(this.no2.getNumber()==no2));
    }
    public boolean isMyNode(NodeObject no1, NodeObject no2) {
        return ((this.no1==no1)&&(this.no2==no2));
    }
    
    public boolean isMyNode(NodeObject no) {
        return (no == no1) || (no == no2);
    }

    public LineObject(TreePanel parent, String name, double x1, double y1, double x2, double y2) {
        setParent(parent);
        setName(name);
        setRect(x1, y1, x2, y2);
    }

    public final void refreshPosition() {
        setRect(no1.getCenterX(), no1.getCenterY(), no2.getCenterX(), no2.getCenterY());
    }

    public NodeObject getNo1() { return no1; }
    public NodeObject getNo2() { return no2; }
    
    
    public LineObject(TreePanel parent, String name, NodeObject no1, NodeObject no2) {
        setParent(parent);
        setName(name);
        this.no1 = no1;
        this.no2 = no2;
        this.no1.addChangeListener(new ChangeListener() {

            public void onChange(ChangeEvent evt) {
                onChangeEvent(evt);
            }
        });
        this.no2.addChangeListener(new ChangeListener() {

            public void onChange(ChangeEvent evt) {
                onChangeEvent(evt);
            }
        });

        refreshPosition();
    }

    public void onChangeEvent(ChangeEvent evt) {
        //System.out.println(evt.toString());
        refreshPosition();
    }

    @Override
    public boolean pointOnMe(double x, double y) {
        boolean l = false;
        boolean t = false;

        if (getLeft() <= getRight()) {
            l = (x >= getLeft() - clickAccuracy) && (x <= getRight() + clickAccuracy);
        } else {
            l = (x <= getLeft() + clickAccuracy) && (x >= getRight() - clickAccuracy);
        }
        if (getTop() <= getBottom()) {
            t = (y >= getTop() - clickAccuracy) && (y <= getBottom() + clickAccuracy);
        } else {
            t = (y <= getTop() + clickAccuracy) && (y >= getBottom() - clickAccuracy);
        }

        if (l && t) {
            return (line.ptLineDist(x, y) <= clickAccuracy);
        } else {
            return false;
        }
    }

    @Override
    public void paint(Graphics2D g) {
        float[] dash2 = {12, 5};

  
        if (isSolution())
            g.setStroke(new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 3,dash2,0));
        else
            g.setStroke(new BasicStroke());
        
        line = new Line2D.Double(getLeft(), getTop(), getRight(), getBottom());
        
        if (isSelected()) {
            g.setColor(getSelectedColor());
        } else {
            if (isSolution())
                g.setColor(getSolutionColor());
            else
                g.setColor(getColor());
        }
        
        g.draw(line);
        
        if ((no2 != null && !getParent().haveOrient(this))||isSolution()||osob) {
            drawArrow(g);
            //g.fillRoundRect(clickAccuracy, clickAccuracy, clickAccuracy, clickAccuracy, clickAccuracy, clickAccuracy);
        }
        
        if (isSolution()) {
            g.setColor(Color.YELLOW);
            int x = (int)((getCenterX()+getRight())/2);
            int y = (int)((getCenterY()+getBottom())/2);
            g.fillRect(x-3, y-10, 20, 13);
            g.setColor(getColor());
            
            g.drawString(getName(), x, y);
        }
    }

    public void drawArrow(Graphics2D g) {
        double X1, Y1, X2, Y2;
        double R;
        double A, B;
        double alph, betta, gamma;
        double x_, y_, c, x0, y0, x1, y1, x2, y2;

        X1 = getLeft();
        Y1 = getTop();

        X2 = getRight();
        Y2 = getBottom();

        R = no2.getRadius() / 2;
        
        A = Y2 - Y1;
        B = X2 - X1;

        if (B != 0) {
            alph = Math.atan(A / B);
            betta = Math.PI / 2 - alph;
        } else {
            alph = Math.PI / 2;
            betta = Math.PI / 2 - alph;
            

            
        }

        if (B > 0) {
            x_ = R * Math.sin(betta);
            y_ = R * Math.cos(betta);
        } else if (B < 0) {
            x_ = -R * Math.sin(betta);
            y_ = -R * Math.cos(betta);
        } else {
            x_ = 0;
            y_ = R;

            
        }


        x0 = X1 + B - x_;
        y0 = Y1 + A - y_;
        /*
        R = Math.sqrt(A * A + B * B) / 2;
        if (B > 0) {
            x_ = R * Math.sin(betta);
            y_ = R * Math.cos(betta);
        } else if (B < 0) {
            x_ = -R * Math.sin(betta);
            y_ = -R * Math.cos(betta);
        } else {
            x_ = 0;
            y_ = R;

            
        }
         */ 
        A = y0 - Y1;
        B = x0 - X1;

        if (B != 0.0) {
            alph = Math.atan(A / B);
            betta = Math.PI / 2 - alph;
        } else {

            alph = Math.PI / 2;
            betta = Math.PI / 2 - alph;
        }

        double u = Math.PI / 6;
        gamma = betta - u;

        
        c = 10 / Math.cos(u);

        if (B > 0) {
            x_ = c * Math.sin(gamma);
            y_ = c * Math.cos(gamma);
        } else if (B < 0) {
            x_ = -c * Math.sin(gamma);
            y_ = -c * Math.cos(gamma);
        } else {
            x_ = 5;
            y_ = 10;
            
        }

        x1 = X1 + B - x_;
        y1 = Y1 + A - y_;

        gamma = alph - u;

        if (B > 0) {
            x_ = c * Math.cos(gamma);
            y_ = c * Math.sin(gamma);
        } else if (B < 0) {
            x_ = -c * Math.cos(gamma);
            y_ = -c * Math.sin(gamma);
        } else {
            x_ = -5;
            y_ = 10;
            
        }

        x2 = X1 + B - x_;
        y2 = Y1 + A - y_;

        if ((getLeft()==getRight())&&(y1<y0)&&(getBottom()<getTop())) 
        {
            y1= getBottom()+R+10;
            y0 = getBottom()+R;
            y2= y1;
        }
        g.draw(new Line2D.Double(x1, y1, x0, y0));
        g.draw(new Line2D.Double(x0, y0, x2, y2));

    }

    @Override
    public void onMouseDragged(GraphicObject source, MouseEvent evt) {
    }

    @Override
    public void onMousePressed(GraphicObject source, MouseEvent evt) {
    }

    @Override
    public void onMouseMoved(GraphicObject source, MouseEvent evt) {
        //setColor(new Color(new Random().nextInt()));
    }

    @Override
    public void onMouseReleased(GraphicObject source, MouseEvent evt) {
    }
}
